package com.minimalist.basic.service.impl;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.minimalist.basic.mapper.MOperatorLogMapper;
import com.minimalist.basic.mapper.MUserMapper;
import com.minimalist.basic.service.OperatorLogService;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.config.request.TenantIdContext;
import com.minimalist.common.config.request.UserIdContext;
import com.minimalist.common.entity.basic.enums.OperatorLogEnum;
import com.minimalist.common.entity.basic.enums.RespEnum;
import com.minimalist.common.entity.basic.enums.UserEnum;
import com.minimalist.common.entity.basic.po.MOperatorLog;
import com.minimalist.common.entity.basic.po.MUser;
import com.minimalist.common.entity.basic.vo.operatorlog.OperatorLogQueryVO;
import com.minimalist.common.entity.basic.vo.operatorlog.OperatorLogVO;
import com.minimalist.common.utils.UnqIdUtil;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.paginate.Page;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 操作日志表 服务层实现。
 *
 * @author 11987
 * @since 2025-01-23
 */
@Service
public class OperatorLogServiceImpl implements OperatorLogService{
    
    private final MOperatorLogMapper operatorLogMapper;
    private final MUserMapper userMapper;
    
    public OperatorLogServiceImpl(MOperatorLogMapper operatorLogMapper, MUserMapper userMapper) {
        this.operatorLogMapper = operatorLogMapper;
        this.userMapper = userMapper;
    }

    @Override
    @SaIgnore
    public void addOperatorLog(OperatorLogVO operatorLogVO){
        MOperatorLog insertOperatorLog = BeanUtil.copyProperties(operatorLogVO, MOperatorLog.class);
        insertOperatorLog.setOperatorLogId(UnqIdUtil.uniqueId());
        int insert = operatorLogMapper.insert(insertOperatorLog, true);
        Assert.isTrue(insert == 1, () -> new BusinessException(RespEnum.FAILED.getDesc()));
        UserIdContext.clear();
        TenantIdContext.clear();
    }

    @Override
    public PageResp<OperatorLogVO> getPageOperatorList(OperatorLogQueryVO queryVO){
        Page<MOperatorLog> operatorLogPage = operatorLogMapper.selectPageOperatorLogList(queryVO);
        List<OperatorLogVO> operatorLogVOList = BeanUtil.copyToList(
                operatorLogPage.getRecords(), OperatorLogVO.class);
        if (operatorLogVOList.isEmpty()){
            return new PageResp<>(operatorLogVOList, 0L);
        }
        List<Long> userIdList = operatorLogVOList.stream()
                .map(OperatorLogVO::getCreateId).toList();
        List<MUser> mUsers = new ArrayList<>();
        LogicDeleteManager.execWithoutLogicDelete(() -> {
            mUsers.addAll(userMapper.selectUserByUserIds(userIdList));
        });
        Assert.notEmpty(mUsers, () -> new BusinessException(
                OperatorLogEnum.ErrorMsg.NONENTITY_OPERATOR_LOG.getDesc()));
        operatorLogVOList.forEach(item -> item.setCreatorName(
                mUsers.stream().filter(user -> user.getUserId().equals(item.getCreateId()))
                        .toList().getFirst().getUsername()));
        return new PageResp<>(operatorLogVOList, operatorLogPage.getTotalRow());
    }

    @Override
    public void deleteOperatorLogByOperatorLogId(Long operatorLogId){
        MOperatorLog operatorLog = operatorLogMapper.selectOperatorLogByOperatorLogId(operatorLogId);
        Assert.notNull(operatorLog,
                () -> new BusinessException(OperatorLogEnum.ErrorMsg.NONENTITY_OPERATOR_LOG.getDesc()));
        int deleteCount = operatorLogMapper.deleteOperatorLogByOperatorLogId(operatorLogId);
        Assert.isTrue(deleteCount == 1,
                () -> new BusinessException(OperatorLogEnum.ErrorMsg.DELETE_OPERATOR_LOG_FAILED.getDesc()));
    }

    @Override
    public OperatorLogVO getOperatorLogByOperatorLogId(Long operatorLogId){
        OperatorLogVO operatorLogVO = BeanUtil.copyProperties(operatorLogMapper
                .selectOperatorLogByOperatorLogId(operatorLogId), OperatorLogVO.class);
        MUser mUser = new MUser();
        LogicDeleteManager.execWithoutLogicDelete(() -> {
            MUser user = userMapper.selectUserByUserId(operatorLogVO.getCreateId());
            Assert.notNull(user, () -> new BusinessException(UserEnum.ErrorMsg.NONENTITY_ACCOUNT.getDesc()));
            BeanUtils.copyProperties(user, mUser);
        });
        operatorLogVO.setCreatorName(mUser.getUsername());
        return operatorLogVO;
    }

    @Override
    public void deleteOperatorLogByOperatorLogIds(List<Long> operatorLogIds){
        operatorLogMapper.deleteUserByUserIds(operatorLogIds);
    }
}
